/*
 * Copyright 2023-2025, Haiku, Inc. All rights reserved.
 * Distributed under the terms of the MIT License.
 */
#ifndef _KERNEL_ARCH_LOONGARCH64_MMU_H
#define _KERNEL_ARCH_LOONGARCH64_MMU_H

#include <arch_cpu.h>

// 定义LoongArch64 TLB相关CSR寄存器
#define CSR_TLBIDX    0x10    // TLB索引
#define CSR_TLBEHI    0x11    // TLB入口高位
#define CSR_TLBELO0   0x12    // TLB入口低位0
#define CSR_TLBELO1   0x13    // TLB入口低位1
#define CSR_ASID      0x18    // 地址空间标识符
#define CSR_PGDL      0x19    // 页表基址低位
#define CSR_PGDH      0x1a    // 页表基址高位
#define CSR_PGD       0x1b    // 页表基址

// 定义TLB操作指令
#define TLBSRCH     0x0       // 搜索TLB
#define TLBRD       0x1       // 读取TLB
#define TLBWR       0x2       // 写入TLB
#define TLBFILL     0x3       // 填充TLB
#define TLBCLR      0x4       // 清除TLB
#define TLBFLUSH    0x5       // 刷新TLB
#define INVTLB      0x6       // 无效化TLB

// 定义TLBIDX寄存器位
#define TLBIDX_PS_SHIFT  24    // 页大小偏移
#define TLBIDX_PS_MASK   0x3f  // 页大小掩码
#define TLBIDX_INDEX_SHIFT 0   // 索引偏移
#define TLBIDX_INDEX_MASK 0xfff // 索引掩码

// 定义INVTLB操作码
#define INVTLB_ALL          0    // 无效化所有TLB
#define INVTLB_ASID         1    // 无效化指定ASID的TLB
#define INVTLB_VA           2    // 无效化指定VA的TLB
#define INVTLB_ASID_VA      3    // 无效化指定ASID和VA的TLB
#define INVTLB_ASID_VA_PAGE 4    // 无效化指定ASID和VA页的TLB

// 定义页大小
#define PS_4K   12   // 4KB页
#define PS_8K   13   // 8KB页
#define PS_16K  14   // 16KB页
#define PS_32K  15   // 32KB页
#define PS_64K  16   // 64KB页
#define PS_128K 17   // 128KB页
#define PS_256K 18   // 256KB页
#define PS_512K 19   // 512KB页
#define PS_1M   20   // 1MB页
#define PS_2M   21   // 2MB页
#define PS_4M   22   // 4MB页
#define PS_8M   23   // 8MB页
#define PS_16M  24   // 16MB页
#define PS_32M  25   // 32MB页
#define PS_64M  26   // 64MB页
#define PS_128M 27   // 128MB页
#define PS_256M 28   // 256MB页
#define PS_512M 29   // 512MB页
#define PS_1G   30   // 1GB页
#define PS_2G   31   // 2GB页
#define PS_4G   32   // 4GB页

// 页表项标志位定义
const uint64 kPteValid = 1ULL << 0;        // V - 有效位
const uint64 kPteRead = 1ULL << 1;         // R - 读权限
const uint64 kPteWrite = 1ULL << 2;        // W - 写权限
const uint64 kPteExec = 1ULL << 3;         // X - 执行权限
const uint64 kPteUser = 1ULL << 4;         // U - 用户态访问权限
const uint64 kPteGlobal = 1ULL << 5;       // G - 全局页
const uint64 kPteAccessed = 1ULL << 6;     // A - 访问位
const uint64 kPteDirty = 1ULL << 7;        // D - 脏位
const uint64 kPteNoCache = 1ULL << 8;      // NC - 非缓存
const uint64 kPtePhysAddrMask = ~0x3ffULL; // 物理地址掩码

// TLB相关函数声明
status_t arch_mmu_tlb_init(kernel_args *args);
status_t arch_mmu_tlb_init_percpu(kernel_args *args, int cpu);
void arch_mmu_tlb_flush(void);
void arch_mmu_tlb_flush_asid(uint32 asid);
void arch_mmu_tlb_flush_va(addr_t vaddr);
void arch_mmu_tlb_flush_asid_va(uint32 asid, addr_t vaddr);
void arch_mmu_tlb_flush_asid_va_page(uint32 asid, addr_t vaddr);
status_t arch_mmu_tlb_read(uint32 index, uint64 *_hi, uint64 *_lo0, uint64 *_lo1);
status_t arch_mmu_tlb_write(uint32 index, uint64 hi, uint64 lo0, uint64 lo1);
status_t arch_mmu_tlb_search(addr_t vaddr, uint32 asid, uint32 *_index);
void arch_mmu_tlb_fill(addr_t vaddr, uint64 lo0, uint64 lo1);
uint32 arch_mmu_tlb_get_entries_count(void);
uint32 arch_mmu_tlb_get_supported_page_sizes(void);
status_t arch_mmu_tlb_miss_handler(addr_t vaddr, bool isWrite);

#endif /* _KERNEL_ARCH_LOONGARCH64_MMU_H */